package com.et114.modules.org.services;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.StringTokenizer;

import net.sf.ehcache.CacheException;

import org.acegisecurity.providers.encoding.Md5PasswordEncoder;

import com.et114.components.acegi.AcegiContext;
import com.et114.components.acegi.Constants;
import com.et114.components.acegi.cache.AcegiCacheManager;
import com.et114.core.common.CONST;
import com.et114.core.exception.CheckException;
import com.et114.core.services.impl.BaseServicesImpl;
import com.et114.core.utility.StringPool;
import com.et114.modules.org.dao.RoleDAO;
import com.et114.modules.org.dao.UserDAO;
import com.et114.modules.org.utility.SessionUserInfo;
import com.et114.modules.org.vo.RoleVo;
import com.et114.modules.org.vo.UserEmplyVo;
import com.et114.modules.org.vo.UserRoleRelVo;
import com.et114.modules.org.vo.UserVo;



/**
 * @author guanhw
 */
public class UserManager extends BaseServicesImpl {
	private Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();
	private UserDAO			userDAO;
	private RoleDAO roleDAO;
	private GroupManager	groupManager;
	
	public void setGroupManager ( GroupManager groupManager ) {
		this.groupManager = groupManager;
	}
	public void setUserDAO ( UserDAO userDAO ) {
		this.userDAO = userDAO;
	}

	
	public Long createUser ( UserVo userVo ) throws CheckException {
		return userDAO.createUser ( userVo ) ; 
	}
	
	public void updateUser ( UserVo userVo ) throws CheckException {
		userDAO.updateUser ( userVo ) ; 
	}
	
	public int removeUser ( UserVo userVo ) throws CheckException { 
		return userDAO.removeUser ( userVo ) ; 
	}
	
	public int  removeUser ( Long id ) {
		UserVo vo = new UserVo() ; 
		vo.setUserId ( id ) ; 
		return userDAO.removeUser ( vo ) ;
	}	
	
	public void createUserRoleRel ( UserRoleRelVo userRoleRel ) throws CheckException {
		userDAO.createUserRoleRel ( userRoleRel ) ; 
	}

	public int deleteUserRoleRel ( UserRoleRelVo userRoleRel ) throws CheckException {
		return userDAO.deleteUserRoleRel ( userRoleRel ) ; 
	}
		
	
	/**
	 * @param vo
	 * @return
	 * @throws CheckException
	 */
	public List getUsersRels ( ) throws CheckException {
		//List users = userDAO.getUsers ( );
		List users = userDAO.getUsersNcRegUser ( new UserVo() ) ; 
		for ( int i = 0 ; i < users.size ( ) ; i ++ ) {
			UserVo user = ( UserVo ) users.get ( i ); //
			userRels( user ) ; 
		}
		return users;
	}
	
	
	
	public void setRoleDAO ( RoleDAO roleDAO ) {
		this.roleDAO = roleDAO;
	}
	

	
	public void userRels ( UserVo user ) throws CheckException {
		// direct roles
		List roles = getAllRolesByUserParams ( ( byte ) 0 , user.getUserId ( ) ) ; //userDAO.getRolesByUser ( user );
		// FIXME indirect roles from emp's titles
		user.setUserEmplyVo ( groupManager.loadEmpWithTitlesByUser ( user.getUserId ( ) ) );
		user.setRoleList ( roles );
	}
	
	public void modifyInCache( UserVo user ) throws CheckException { 
		userRels( user ) ; 
		AcegiCacheManager.getInstansce ( ).modifyUserInCache ( user ) ;
	}
	
	public void userRoleRelModifyInCache( UserVo user , List roles , byte mm ) throws CheckException { 
		if ( roles == null || roles.size ( ) == 0 ) return ; 
		if ( user == null  ) return ;
		Object[] objs = new Object[ roles.size ( ) ] ;
		for ( int  i = 0 ; i < roles.size ( )  ; i ++ ) {
			RoleVo role = ( RoleVo ) roles.get ( i ); 
			if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
				objs[ i ] =  role.getRoleName ( ) ;
			else objs[ i ] = role.getRoleId ( ) ;
		}
		
		if ( AcegiCacheManager.getInstansce ( ).getUserDetailsByUserId ( user.getLoginName ( ) ) == null ) {
			logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
			OrgFactory.getUserManager ( ).modifyInCache (  user ) ;
		}
		else 								
			AcegiCacheManager.getInstansce ( ).modUserAuthorityCache (
					user.getLoginName ( ) , mm , Constants.AUTH_TYPE_ROLE , objs , false );
	}
	
	public void userRoleRelModifyInCache( UserVo user , Long[] roleIds , byte mm ) throws CheckException { 
		if ( user == null  || roleIds == null|| roleIds.length == 0 ) return;		
		RoleVo role = new RoleVo() ; 
		role.setRoleIds ( roleIds ) ; 
		List roles = roleDAO.getRoles ( role ) ; 
		userRoleRelModifyInCache( user , roles , mm ) ; 
	}
	
	public void modifyUserPasswordInCache( String loginName , String password ,  boolean isworkflg ) throws CheckException { 
		AcegiCacheManager.getInstansce ( ).modifyUserPasswordInCache(loginName, password, isworkflg);
	}
	
	public List getRolesByUser( byte roleType , Long userId ) throws CheckException { 
		Map params = new HashMap ( );
		params.put ( "userId" , userId );
		params.put ( "roleType" , new Integer ( roleType ) ); 
		return getRolesByUsers( params ) ; 
	}

	
	public List getRolesByUsers ( java.util.Map params ) throws CheckException {
		return userDAO.getRolesByUser ( params );
	}
	
	public List getAllRolesByUserParams( byte roleType , Long userId ) throws CheckException { 
		Map params = new HashMap ( );
		params.put ( "userId" , userId );
		params.put ( "roleType" , new Integer ( roleType ) ); 
		return getAllRolesByUserParams( params ) ; 
	}
	
	public List getAllRolesByUserParams( java.util.Map params ) throws CheckException { 
		return userDAO.getAllRolesByUserParams ( params );
	}
	
	public UserVo loadUserByLoginName ( String loginName ) {
		return userDAO.loadUserByLoginName ( loginName ) ;
	}
	
	public Integer getMaxRoleTypeByUserId( Long userId ) throws CheckException {
		return userDAO.getMaxRoleTypeByUserId ( userId ) ; 
	}
	
	public UserEmplyVo getUserEmplyByEmpId ( Long empId ) throws CheckException {
		return userDAO.getUserEmplyByEmpId ( empId );
	}
	
	public UserVo getUserById ( Long userId ) throws CheckException {
		return userDAO.getUserById ( userId );
	}
	
	public List getFunctionsByUser ( Long userId ) throws CheckException {
		return userDAO.getFunctionsByUser ( userId );
	}
	
	public SessionUserInfo getSessionUserInfoByLoginNameAndPassword (
			String loginName , String password ) throws CheckException {
		return userDAO.getSessionUserInfoByLoginNameAndPassword ( loginName ,
				password );
	}
	


	
	public void deleteUserRoleRel( UserVo user , Long[] roleIds , Long operId ) throws CheckException , CacheException  { 
		if ( roleIds == null || roleIds.length == 0 || user == null) return; 
		for ( int i = 0 ; i < roleIds .length ; i ++  ) {
			UserRoleRelVo userRoleRel = new UserRoleRelVo() ;
			Long roleId = roleIds[ i ] ;
			userRoleRel.setRoleId ( roleId );
			userRoleRel.setUserId ( user.getUserId ( ) );
			userRoleRel.setOperUser ( operId );
			userDAO.deleteUserRoleRel ( userRoleRel ) ;
		}
		userRoleRelModifyInCache( user , roleIds ,  Constants.CACHE_DEL   ) ;
	}

	public List queryRolesOfUser ( UserVo userVo , byte page ) throws CheckException {
		if( page == CONST.PAGE ) return userDAO.getRolesByUser ( userVo ); 
		return userDAO.getRolesByUserNPage ( userVo ); 
	}
	
	public Long countgetRolesByUser( UserVo userVo ) throws CheckException { 
		return userDAO.countgetRolesByUser( userVo ) ; 
	}
	
	
	public List getSearchUsers ( UserVo userVo ) throws CheckException {
		return userDAO.getSearchUsers ( userVo );
	}
	
	/**
	 * 个人用户密码修改
	 * 
	 * @param uservo
	 */
	public synchronized void updatePassword ( UserVo uservo ) {
		uservo.setPassword ( md5PasswordEncoder.encodePassword ( uservo.getPassword ( ) , null ) );
		userDAO.updateUser ( uservo );
		modifyUserPasswordInCache ( uservo.getLoginName ( ) , uservo.getPassword ( ) , uservo.getWorkFlg ( ).booleanValue ( ) );
	}
	

	/**
	 * 批量或查询用户密码修改
	 * 
	 * @param uservo
	 */
	public synchronized void updateAllPassword ( UserVo uservo , List userlist ) {
		String password = md5PasswordEncoder.encodePassword ( uservo
				.getPassword ( ) , null );
		uservo.setPassword ( password );
		userDAO.updateAllUser ( uservo );
		for ( int i = 0 ; i < userlist.size ( ) ; i ++ ) {
			uservo = ( UserVo ) userlist.get ( i );
			modifyUserPasswordInCache ( uservo.getLoginName ( ) , password ,
					uservo.getWorkFlg ( ).booleanValue ( ) );
		}
	}
	
	/**
	 * 查询所有用户
	 * 
	 * @param uservo
	 */
	public List getEmpAllList ( UserVo uservo ) {
		return userDAO.getEmpAllList ( uservo );
	}
	
	public Long countEmpAllList ( UserVo userVo ) throws CheckException {
		return userDAO.countEmpAllList ( userVo );
	}

	
	public boolean checkExistsUserByLoginName( String loginName )  throws CheckException { 
		return userDAO.checkExistsUserByLoginName ( loginName ) ; 
	}
	
	public synchronized void saveUserRoleRel( UserVo userVo , byte roleType , String principalIds  ) throws CheckException  , CacheException {
		Long userId = userVo.getUserId ( ) ; 
		List roles = new ArrayList( ) ; 
		List tmpRoles = new java.util.ArrayList();
		if ( principalIds != null ) {
			roles = getRolesByUser ( roleType , userId  ) ;
			principalIds = principalIds.trim ( ) ; 
			StringTokenizer st = new StringTokenizer( principalIds , StringPool.SEMICOLON ) ;
			int count = st.countTokens ( ) ;
			for ( int i = 0 ; i < count ; i ++  ) {
				String nt = st.nextToken ( ) ;
				//check
				boolean mark = false ;
				if ( roles.size() == 0  )  mark = true;
				for ( Iterator iter = roles.iterator ( ); iter.hasNext ( ) ;  ) {
					RoleVo role = ( RoleVo )  iter.next ( );
					Long roleId = role.getRoleId ( );
					if ( roleId .toString ( ).equals ( nt ) ) {
						iter.remove ( );
						mark = false ;
						break;
					}
					else mark = true ;
				}

				if ( mark  ) tmpRoles.add ( nt ) ;
			}	
			
				Long[] objs = new Long[ tmpRoles.size ( ) ]  ;
			    int i = 0 ;
				for ( Iterator iter = tmpRoles.iterator ( ); iter.hasNext ( ) ;  ) {
					Long principalId = Long.valueOf ( iter.next ( ).toString ( ) ) ;
					objs[ i ] = principalId ;
					UserRoleRelVo userRoleRel = new UserRoleRelVo() ;
					userRoleRel.setRoleId ( principalId ) ;
					userRoleRel.setUserId ( userId ) ;
					userRoleRel.setOperUser ( userVo.getOperUser ( ) );
					userRoleRel.setCrtUser ( userVo.getCrtUser ( ) ) ; 
					createUserRoleRel( userRoleRel ) ;
					i ++ ;
				}	
				//do cache since 1.33 
				if ( objs.length > 0 ) 
					userRoleRelModifyInCache ( userVo , objs , Constants.CACHE_NEW ) ;

				
				for ( Iterator iter = roles.iterator ( ); iter.hasNext ( ) ;  ) {
					RoleVo role = ( RoleVo )  iter.next ( );
					Long principalId = role.getRoleId ( );
					UserRoleRelVo userRoleRel = new UserRoleRelVo() ;
					userRoleRel.setRoleId ( principalId ) ;
					userRoleRel.setUserId ( userId ) ;
					userRoleRel.setOperUser ( userVo.getOperUser ( ) );
					userDAO.deleteUserRoleRel ( userRoleRel ) ;
				}
				//do cache since 1.33 
				if ( roles.size ( ) > 0 ) 
					userRoleRelModifyInCache ( userVo , roles , Constants.CACHE_DEL ) ;
					
				//do cache since 1.33 
				/*if ( roles.size ( ) > 0 || tmpRoles.size ( ) > 0 ) {
					modifyInCache ( userVo ) ;
				}*/
					
		}
	}	
	
}